package net.subaquatic;

import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.ws.WebServiceRef;
import net.subaquatic.sfdc.jaxws.CallOptions;
import net.subaquatic.sfdc.jaxws.Create;
import net.subaquatic.sfdc.jaxws.CreateResponse;
import net.subaquatic.sfdc.jaxws.ErrorType;
import net.subaquatic.sfdc.jaxws.Login;
import net.subaquatic.sfdc.jaxws.LoginResponse;
import net.subaquatic.sfdc.jaxws.LoginScopeHeader;
import net.subaquatic.sfdc.jaxws.Logout;
import net.subaquatic.sfdc.jaxws.ObjectFactory;
import net.subaquatic.sfdc.jaxws.SObject;
import net.subaquatic.sfdc.jaxws.SaveResultType;
import net.subaquatic.sfdc.jaxws.SessionHeader;
import net.subaquatic.sfdc.jaxws.SforceService;
import net.subaquatic.sfdc.jaxws.Soap;
import net.subaquatic.sfdc.jaxws.UnexpectedErrorFault_Exception;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * Servlet that interacts with the Salesforce.com Web Services.
 * @author Jason Howk
 */
@WebServlet(name = "CreateLead", urlPatterns = {"/CreateLead"})
public class CreateLead extends HttpServlet {

    static final Logger logger = Logger.getLogger("net.subaquatic.CreateLead");
    static final String username = "wsuser@subaquatic.net";
    static final String password = "p@ssw0rd17VxGRoXtfUQXM3ShTIJFLAoy";
    @WebServiceRef(wsdlLocation = "WEB-INF/wsdl/partner.wsdl")
    private SforceService service;

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // Forward back to JSP to render w/ additional data.
        RequestDispatcher rd = request.getRequestDispatcher("createLead.jsp");

        // Call Web Service Operation
        logger.log(Level.INFO, "Getting Soap Reference");
        Soap port = service.getSoap();
        SessionHeader sessionHeader = new SessionHeader();
        CallOptions options = new CallOptions();

        try {
            // Initialize WS operation arguments here
            Login parameters = new Login();
            parameters.setUsername(username);
            parameters.setPassword(password);

            // Login In.
            logger.log(Level.INFO, "Logging In");
            LoginScopeHeader loginHeader = new LoginScopeHeader();
            LoginResponse result = port.login(parameters, loginHeader, options);

            logger.log(Level.INFO, "Setting new endpoint.");
            /* You can manipulate the URL to replace the HTTPS with HTTP in order to
             * sniff the connection and see what's happening.
             * DO NOT DO THIS IN PRODUCTION.
             */
            //SfSoapHandler.setEndpoint(result.getResult().getServerUrl().replace(new StringBuilder("https"), new StringBuilder("http")));
            SfSoapHandler.setEndpoint(result.getResult().getServerUrl());
            logger.log(Level.INFO, "Finished Seting endpoint.");

            logger.log(Level.INFO, "Setting session ID.");
            sessionHeader.setSessionId(result.getResult().getSessionId());
            logger.log(Level.INFO, "Set session ID: {0}", result.getResult().getSessionId());

            ObjectFactory soFactory = new ObjectFactory();

            // Start to create the new Lead object.
            SObject leads = new SObject();
            leads.setType("Lead");
            Create cl = new Create();
            List<Object> elements = leads.getAny();

            // Create Element
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.newDocument();
            Element element;
            // First Name
            element = builder.newDocument().createElement("FirstName");
            element.setTextContent(request.getParameter("FirstName"));
            elements.add(element);
            // Last Name
            element = builder.newDocument().createElement("LastName");
            element.setTextContent(request.getParameter("LastName"));
            elements.add(element);
            // Company Name
            element = builder.newDocument().createElement("Company");
            element.setTextContent(request.getParameter("CompanyName"));
            elements.add(element);
            // Status
            element = builder.newDocument().createElement("Status");
            element.setTextContent("Open");
            elements.add(element);
            // Phone Number
            element = doc.createElement("Phone");
            element.setTextContent(request.getParameter("PhoneNumber"));
            elements.add(element);
            // Description (used to create a numerical order of records injected.
            element = doc.createElement("Title");
            element.setTextContent(String.valueOf(System.currentTimeMillis()));
            elements.add(element);

            cl.getSObjects().add(leads);
            logger.log(Level.INFO, "Creating Lead.");
            CreateResponse cr = port.create(cl, sessionHeader, options, null, null, null, null, null, null, null);
            
            for (SaveResultType srt : cr.getResult()) {
                if (srt.isSuccess()) {
                    logger.log(Level.INFO, "Created Lead: {0}", srt.getId());
                    // Put the new ID back into the request.
                    request.setAttribute("leadId", srt.getId());
                } else {
                    for (ErrorType et : srt.getErrors()) {
                        logger.log(Level.WARNING, "ERROR ENCOUNTERED CREATING OBJECT: {0}", et.getMessage());
                        throw new Exception(et.getMessage());
                    }
                }
            }
        } catch (Exception ex) {
            logger.log(Level.WARNING, "ERROR: {0}", ex.getMessage());
            request.setAttribute("error", ex.getMessage());
        }

        Logout logoutParams = new Logout();
        try {
            port.logout(logoutParams, sessionHeader, options);
            logger.log(Level.INFO, "Logged Out.");
        } catch (UnexpectedErrorFault_Exception ex) {
            //Don't care for now...
        }

        // Forward back to the createLead.jsp for rendering
        rd.forward(request, response);
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}
